else if (argv[1][1] == 'w')
buf.mode |= 2;
- buf.device = atol(argv[3]) + atol(argv[6]);
+ buf.device = atol(argv[3]);
buf.start_sect = atol(argv[4]);
buf.n_sectors = atol(argv[5]);
+ buf.partition = atol(argv[6]);
asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[2]);
fd = open(strbuf, O_WRONLY);
for (x = 0; x < buf.n_aces; x++) {
char read = ( buf.entries[x].mode & 1 ? 'r' : ' ' );
char write = ( buf.entries[x].mode & 2 ? 'w' : ' ' );
- printf("%x %lx %lx %c%c\n", buf.entries[x].device,
+ printf("%x %x %lx %lx %c%c\n", buf.entries[x].device,
+ buf.entries[x].partition,
buf.entries[x].start_sect,
buf.entries[x].n_sectors,
read,
struct list_head list;
unsigned short device;
+ unsigned short partition;
unsigned long start_sect;
unsigned long n_sectors;
int mode;
struct list_head *cur_ace_head;
struct physdisk_ace *cur_ace;
- dev &= ~0x1f; /* ignore the partition part */
-
list_for_each(cur_ace_head, &p->physdisk_aces) {
cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
list);
sect);
if (sect >= cur_ace->start_sect &&
sect < cur_ace->start_sect + cur_ace->n_sectors &&
- dev == (cur_ace->device & ~0x1f) && /* ignore partition part */
+ dev == cur_ace->device &&
((operation == READ && (cur_ace->mode & PHYSDISK_MODE_R)) ||
(operation == WRITE && (cur_ace->mode & PHYSDISK_MODE_W)))) {
DPRINTK("Yes.\n");
ace_end = cur_ace->start_sect + cur_ace->n_sectors;
if (cur_ace->start_sect >= kill_zone_end ||
ace_end <= start_sect ||
- (cur_ace->device & ~0x1f) != (dev & ~0x1f))
+ cur_ace->device != dev)
continue;
DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n",
/* Cut the current ace down to just the bit before the kzone,
create a new ace for the bit just after it. */
new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
- new_ace->device = dev & ~0x1f;
+ new_ace->device = dev;
new_ace->start_sect = kill_zone_end;
new_ace->n_sectors = ace_end - kill_zone_end;
new_ace->mode = cur_ace->mode;
/* Hold the lock on entry, it remains held on exit. */
static int xen_physdisk_grant_access(unsigned short dev,
+ unsigned short partition,
unsigned long start_sect,
unsigned long n_sectors,
int mode,
cur_ace->start_sect = start_sect;
cur_ace->n_sectors = n_sectors;
cur_ace->mode = mode;
+ cur_ace->partition = partition;
list_add_tail(&cur_ace->list, &p->physdisk_aces);
}
cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
list);
buf->entries[n_aces].device = cur_ace->device;
+ buf->entries[n_aces].partition = cur_ace->partition;
buf->entries[n_aces].start_sect = cur_ace->start_sect;
buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
buf->entries[n_aces].mode = cur_ace->mode;
}
spin_lock(&p->physdev_lock);
res = xen_physdisk_grant_access(xpd->device,
+ xpd->partition,
xpd->start_sect,
xpd->n_sectors,
xpd->mode,
int mode; /* 0 -> revoke existing access, otherwise bitmask of
PHYSDISK_MODE_? constants */
int domain;
- unsigned short device;
+ unsigned short device; /* XENDEV_??? + idx */
+ unsigned short partition; /* partition number */
unsigned long start_sect;
unsigned long n_sectors;
} xp_disk_t;
-#define PHYSDISK_MAX_ACES_PER_REQUEST 254
+#define PHYSDISK_MAX_ACES_PER_REQUEST 254 /* Make it fit in one page */
typedef struct {
int n_aces;
int domain;
int start_ind;
struct {
- unsigned short device;
+ unsigned short device; /* XENDEV_??? + idx */
+ unsigned short partition; /* partition number */
unsigned long start_sect;
unsigned long n_sectors;
unsigned mode;
#include <asm/uaccess.h>
#include <linux/proc_fs.h>
+#include "xl_block.h"
+
extern int xenolinux_control_msg(int operration, char *buffer, int size);
+extern unsigned short xldev_to_physdev(kdev_t xldev);
+
+static dev_t physdev_to_xldev(unsigned short physdev)
+{
+ switch (physdev & XENDEV_TYPE_MASK) {
+ case XENDEV_IDE:
+ switch (physdev & XENDEV_IDX_MASK) {
+ case 0 ... (XLIDE_DEVS_PER_MAJOR-1):
+ return MKDEV(XLIDE_MAJOR_0,
+ (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT);
+ case XLIDE_DEVS_PER_MAJOR ... (XLIDE_DEVS_PER_MAJOR * 2 - 1):
+ return MKDEV(XLIDE_MAJOR_1,
+ (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT);
+ }
+ break;
+ case XENDEV_SCSI:
+ return MKDEV(XLSCSI_MAJOR,
+ (physdev & XENDEV_IDX_MASK) << XLSCSI_PARTN_SHIFT);
+ case XENDEV_VIRTUAL:
+ return MKDEV(XLVIRT_MAJOR,
+ (physdev & XENDEV_IDX_MASK) << XLVIRT_PARTN_SHIFT);
+ }
+ printk(KERN_ALERT "Unrecognised xl device: %x\n", physdev);
+ BUG();
+ return -1;
+}
static ssize_t proc_read_phd(struct file * file, char * buff, size_t size,
loff_t * off)
physdisk_probebuf_t *buf;
int res;
struct proc_dir_entry *pde;
+ int x;
if (size != sizeof(physdisk_probebuf_t))
return -EINVAL;
if (!buf)
return -ENOMEM;
- if (copy_from_user(buf, buff, size)) {
- kfree(buf);
- return -EFAULT;
- }
-
pde = file->f_dentry->d_inode->u.generic_ip;
buf->domain = (int)pde->data;
if (res)
res = -EINVAL;
else {
+ for (x = 0; x < buf->n_aces; x++)
+ buf->entries[x].device = physdev_to_xldev(buf->entries[x].device);
res = sizeof(physdisk_probebuf_t);
if (copy_to_user(buff, buf, sizeof(physdisk_probebuf_t))) {
res = -EFAULT;
pde = file->f_dentry->d_inode->u.generic_ip;
xpd->domain = (int)pde->data;
+ xpd->device = xldev_to_physdev(xpd->device);
res = xenolinux_control_msg(XEN_BLOCK_PHYSDEV_GRANT, local, count);
if (res == 0)
count = 0;
for (i = 0; i < buf->n_aces; i++) {
- if ((buf->entries[i].device & 0x1f) == 0)
+ if (buf->entries[i].partition == 0)
continue;
/* Make sure the partition is actually supposed to be on this
disk. This assumes that Xen and XenoLinux block device
numbers match up. */
- if ((buf->entries[i].device & ~0x1f) != bdev->bd_dev)
+ if (buf->entries[i].device != bdev->bd_dev)
continue;
/* This is a bit of a hack - the partition numbers are specified
by the hypervisor, and if we want them to match up, this is
what we need to do. */
count ++;
- minor = (buf->entries[i].device & 0x1f) + first_part_minor - 1;
+ minor = buf->entries[i].partition + first_part_minor - 1;
add_gd_partition(hd,
minor,
buf->entries[i].start_sect,